import React, {
  ReactElement,
  useEffect,
  useState,
  useContext,
  useCallback
} from 'react';
import {
  View,
  Text,
  Image,
  DeviceEventEmitter,
  EmitterSubscription
} from 'react-native';
import { Surface, Shape, Path } from '@react-native-community/art';

import styles from './style';
import { liveEndIcon } from '../../../../constant/resource';
import { px } from '../../../../util/adapt';
import { entryClassRoom, getVideoName } from '../../actions';
import { Store } from '../../reducer';
import Log from '../../../../common/log';
import netSpeed from '../../../../util/native/netSpeed';
import tracker from '../../../../util/actionTracker';
import {
  finishClassRoomPreDownloadVideo,
  preDownloadingClassRoomVideo
} from '../../../../constant/events';
import { getVideoTasksByParentId } from '../../../../util/videoDownload/videoDownloadStore';
import { getVideoTaskCanPlay } from '../../../../util/videoDownload/videoDownloadManage';
import {
  DOWNLOAD_VIDEO_TASK_PROGRESS,
  DOWNLOAD_VIDEO_TASK_SUCCESS
} from '../../../../util/videoDownload/constant';
import { DownloadVideoTaskProps } from '../../../../util/videoDownload/types';

const TAG = 'downloadResource';
let reportNetSpeedTimer: NodeJS.Timer | null = null;

export default (): ReactElement => {
  const [progress, setProgress] = useState(0);
  const [downloadedNum, setDownloadedNum] = useState(1);

  const { state } = useContext(Store);
  const {
    showDownloadResource,
    lesson,
    mustDownloadVideoUrls,
    needDownloadVideoNum,
    isNeedPreloadResource,
    type
  } = state;
  const { lessonResourceId } = lesson;

  const judgeCanPlay = useCallback((): boolean => {
    const tasks = getVideoTasksByParentId(lessonResourceId);
    for (let i = 0; i < mustDownloadVideoUrls.length; i += 1) {
      const url = mustDownloadVideoUrls[i];
      const task = tasks[`${lessonResourceId}-${getVideoName(url)}`];
      const canPlay = task ? getVideoTaskCanPlay(task) : false;
      if (!canPlay) {
        Log.i(
          TAG,
          JSON.stringify({
            event: 'judgeCanPlay',
            mustDownloadVideoUrls,
            task,
            canPlay,
            url
          })
        );
        return false;
      }
    }

    Log.i(
      TAG,
      JSON.stringify({
        event: 'judgeCanPlay',
        mustDownloadVideoUrls,
        canPlay: true
      })
    );
    return true;
  }, [lessonResourceId, mustDownloadVideoUrls]);

  useEffect((): (() => void) => {
    let successSubscription: EmitterSubscription | null = null;
    let progressSubscription: EmitterSubscription | null = null;

    const removeTimeAndSubscription = (): void => {
      if (reportNetSpeedTimer) {
        clearTimeout(reportNetSpeedTimer);
      }
      if (successSubscription) {
        successSubscription.remove();
      }
      if (progressSubscription) {
        progressSubscription.remove();
      }
    };

    if (
      !(lessonResourceId && showDownloadResource && needDownloadVideoNum !== 0)
    ) {
      removeTimeAndSubscription();
    } else if (judgeCanPlay() || !isNeedPreloadResource) {
      Log.i(
        TAG,
        JSON.stringify({
          event: 'checkEntryClassRoom',
          isNeedPreloadResource,
          needDownloadVideoNum
        })
      );
      entryClassRoom();

      setProgress(1);
    } else {
      // 初始化已下载数量
      let hasReportNetSpeed = false;
      const startTime = new Date().getTime();
      const startAppBytes = netSpeed.getUidRxBytes(0);

      const reportNetSpeed = (startReportBytes: number): void => {
        reportNetSpeedTimer = setTimeout((): void => {
          const endReportBytes = netSpeed.getUidRxBytes(0);
          const reportMBytes = (endReportBytes - startReportBytes) / 1024;

          Log.i(
            TAG,
            JSON.stringify({
              event: 'preDownloadingClassRoomVideo',
              netSpeed: reportMBytes / 10
            })
          );
          tracker.reportAction(preDownloadingClassRoomVideo, {
            netSpeed: reportMBytes / 10
          });

          reportNetSpeed(netSpeed.getUidRxBytes(0));
        }, 10 * 1000);
      };

      reportNetSpeed(netSpeed.getUidRxBytes(0));

      successSubscription = DeviceEventEmitter.addListener(
        DOWNLOAD_VIDEO_TASK_SUCCESS,
        (task: DownloadVideoTaskProps): void => {
          Log.i(
            TAG,
            JSON.stringify({
              event: 'downloadResourceSuccess',
              urls: task.urls
            })
          );
          if (task.parentId !== lessonResourceId) {
            return;
          }
          setDownloadedNum((num): number => {
            return num < needDownloadVideoNum ? num + 1 : num;
          });
        }
      );

      progressSubscription = DeviceEventEmitter.addListener(
        DOWNLOAD_VIDEO_TASK_PROGRESS,
        (task: DownloadVideoTaskProps): void => {
          if (judgeCanPlay()) {
            removeTimeAndSubscription();
            Log.i(
              TAG,
              JSON.stringify({
                event: 'entryClassRoom need download resource',
                isNeedPreloadResource
              })
            );
            if (!hasReportNetSpeed) {
              const endTime = new Date().getTime();
              const endAppBytes = netSpeed.getUidRxBytes(0);
              const appMBytes = (endAppBytes - startAppBytes) / 1024;
              const totalDuration = endTime - startTime;
              Log.i(
                TAG,
                JSON.stringify({
                  event: 'preDownloadAllResourceSuccess',
                  playDuration: totalDuration,
                  netSpeed: appMBytes / (totalDuration / 1000)
                })
              );
              tracker.reportAction(finishClassRoomPreDownloadVideo, {
                playDuration: totalDuration,
                netSpeed: appMBytes / (totalDuration / 1000)
              });
              hasReportNetSpeed = true;
            }

            entryClassRoom();
            if (reportNetSpeedTimer) {
              clearTimeout(reportNetSpeedTimer);
              reportNetSpeedTimer = null;
            }
            setProgress(1);
            return;
          }
          if (
            task.parentId === lessonResourceId &&
            mustDownloadVideoUrls.includes(task.urls[0])
          ) {
            setProgress(task.progress);
          }
        }
      );
    }

    return (): void => {
      removeTimeAndSubscription();
    };
  }, [
    isNeedPreloadResource,
    judgeCanPlay,
    lessonResourceId,
    mustDownloadVideoUrls,
    needDownloadVideoNum,
    showDownloadResource,
    type
  ]);

  const path = new Path()
    .moveTo(px(9), 0)
    .lineTo(px(19), 0)
    .lineTo(px(10), px(12))
    .lineTo(0, px(12))
    .close();

  if (!showDownloadResource) return <View />;

  return (
    <View style={styles.container}>
      <Image source={liveEndIcon} style={styles.icon} resizeMode="contain" />
      <Text style={styles.desc}>
        资源加载中…{Math.floor(progress * 100)}%{' '}
        {needDownloadVideoNum ? `${downloadedNum}/${needDownloadVideoNum}` : ''}
      </Text>
      <View style={styles.progressContent}>
        <View style={[styles.progress, { width: px(500) * progress }]}>
          {new Array(22).fill('').map(
            (item, index): ReactElement => (
              <Surface
                // eslint-disable-next-line react/no-array-index-key
                key={`resource-${index}`}
                width={px(19)}
                height={px(12)}
                style={{ marginRight: px(4) }}
              >
                <Shape d={path} fill="#E9D24C" />
              </Surface>
            )
          )}
        </View>
      </View>
    </View>
  );
};
